package com.star.mentor.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.star.mentor.dto.EvaluationItemUpdateDTO;
import com.star.mentor.dto.EvaluationLogPageDTO;
import com.star.mentor.dto.EvaluationUpdateDTO;
import com.star.mentor.entity.Evaluation;
import com.star.mentor.entity.EvaluationItem;
import com.star.mentor.entity.EvaluationLog;
import com.star.mentor.enums.EvaluationItemType;
import com.star.mentor.enums.EvaluationLogType;
import com.star.mentor.mapper.EvaluationLogMapper;
import com.star.mentor.service.EvaluationItemService;
import com.star.mentor.service.EvaluationLogService;
import com.star.mentor.service.EvaluationService;
import com.star.mentor.vo.EvaluationLogPageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 评估项目更改日志 服务实现类
 *
 * @author yangzj
 */
@Service
public class EvaluationLogServiceImpl extends ServiceImpl<EvaluationLogMapper, EvaluationLog> implements EvaluationLogService {
    @Autowired
    private EvaluationService evaluationService;
    @Autowired
    private EvaluationItemService evaluationItemService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(EvaluationUpdateDTO dto) {
        List<EvaluationLog> resultList = new ArrayList<>();
        resultList.addAll(this.buildBaseInfoChange(dto));
        resultList.addAll(this.buildItemChange(dto.getId(), dto.getItems()));
        this.saveBatch(resultList);
    }

    @Override
    public void saveEnabledChange(Long evaluationId, boolean oldEnabled, boolean newEnabled) {
        String fieldName = "是否启用";
        this.save(new EvaluationLog().setEvaluationId(evaluationId)
                .setType(EvaluationLogType.OTHER.getCode())
                .setOldData(fun.apply(fieldName, enabledFun.apply(oldEnabled)))
                .setNewData(fun.apply(fieldName, enabledFun.apply(newEnabled))));
    }

    @Override
    public IPage<EvaluationLogPageVO> page(EvaluationLogPageDTO dto) {
        return baseMapper.page(dto);
    }

    /**
     * 构建基础信息改变
     *
     * @param dto 入参
     * @return {@link List}<{@link EvaluationLog}>
     */
    public List<EvaluationLog> buildBaseInfoChange(EvaluationUpdateDTO dto) {
        Evaluation old = evaluationService.getById(dto.getId());
        List<EvaluationLog> resultList = new ArrayList<>();
        StringBuilder old1 = new StringBuilder();
        StringBuilder new1 = new StringBuilder();

        if (!Objects.equals(dto.getName(), old.getName())) {
            String fieldName = "规则名称";
            old1.append(fun.apply(fieldName, old.getName()));
            new1.append(fun.apply(fieldName, dto.getName()));
        }
        if (!Objects.equals(dto.getRemark(), old.getRemark())) {
            String fieldName = "备注";
            old1.append(fun.apply(fieldName, old.getName()));
            new1.append(fun.apply(fieldName, dto.getRemark()));
        }
        if (old1.length() > 0) {
            resultList.add(new EvaluationLog().setEvaluationId(old.getId())
                    .setType(EvaluationLogType.BASE_ITEM.getCode())
                    .setOldData(old1.toString())
                    .setNewData(new1.toString()));
        }
        StringBuilder old2 = new StringBuilder();
        StringBuilder new2 = new StringBuilder();
        if (!Objects.equals(dto.getIsMultiple(), old.getIsMultiple())) {
            String fieldName = "是否多人评估";
            old2.append(fun.apply(fieldName, isFun.apply(old.getIsMultiple())));
            new2.append(fun.apply(fieldName, isFun.apply(dto.getIsMultiple())));
        }
        if (!Objects.equals(dto.getIcon(), old.getIcon())) {
            String fieldName = "图标";
            old2.append(fun.apply(fieldName, old.getIcon()));
            new2.append(fun.apply(fieldName, dto.getIcon()));
        }
        if (old2.length() > 0) {
            resultList.add(new EvaluationLog().setEvaluationId(old.getId())
                    .setType(EvaluationLogType.OTHER.getCode())
                    .setOldData(old2.toString())
                    .setNewData(new2.toString()));
        }
        return resultList;
    }

    /**
     * 构建项目改变
     *
     * @param items        项目
     * @param evaluationId 评价ID
     * @return {@link List}<{@link EvaluationLog}>
     */
    private List<EvaluationLog> buildItemChange(Long evaluationId, List<EvaluationItemUpdateDTO> items) {
        List<EvaluationItem> oldItems = evaluationItemService.list(Wrappers.<EvaluationItem>lambdaQuery().eq(EvaluationItem::getEvaluationId, evaluationId));
        if (CollUtil.isEmpty(items)) {
            if (CollUtil.isEmpty(oldItems)) {
                return new ArrayList<>();
            }
            // 全部删了
            return this.listDeletedItem(evaluationId, oldItems);
        }
        if (CollUtil.isEmpty(oldItems)) {
            // 全部算新增
            return this.listAddedItem(evaluationId, items);
        }
        List<EvaluationLog> resultList = new ArrayList<>();
        List<Long> newIds = items.stream().map(EvaluationItemUpdateDTO::getId).filter(Objects::nonNull).collect(Collectors.toList());
        // 删除的项目
        List<EvaluationItem> deletedItems = oldItems.stream().filter(c -> !newIds.contains(c.getId())).collect(Collectors.toList());
        if (!deletedItems.isEmpty()) {
            resultList.addAll(this.listDeletedItem(evaluationId, deletedItems));
        }
        items.forEach(c -> {
            Optional<EvaluationItem> first = oldItems.stream().filter(b -> b.getId().equals(c.getId())).findFirst();
            if (first.isPresent()) {
                EvaluationItem old = first.get();
                // 老的，要判断是否有修改
                StringBuilder newer = new StringBuilder();
                StringBuilder older = new StringBuilder();
                if (!Objects.equals(old.getType(), c.getType())) {
                    newer.append(fun.apply("项目类型", EvaluationItemType.getName(c.getType())));
                    older.append(fun.apply("项目类型", EvaluationItemType.getName(old.getType())));
                }
                if (!Objects.equals(old.getName(), c.getName())) {
                    newer.append(fun.apply("项目名称", c.getName()));
                    older.append(fun.apply("项目名称", old.getName()));
                }
                if (!Objects.equals(old.getDescription(), c.getDescription())) {
                    newer.append(fun.apply("项目描述", c.getDescription()));
                    older.append(fun.apply("项目描述", old.getDescription()));
                }
                if (!Objects.equals(old.getScore(), c.getScore())) {
                    newer.append(fun.apply("项目分值", c.getScore() + ""));
                    older.append(fun.apply("项目分值", old.getScore() + ""));
                }
                resultList.add(new EvaluationLog().setEvaluationId(evaluationId)
                        .setType(EvaluationLogType.BASE_ITEM.getCode())
                        .setOldData(older.toString())
                        .setNewData(newer.toString()));
            } else {
                // 新增的
                resultList.addAll(this.listAddedItem(evaluationId, Collections.singletonList(c)));
            }
        });
        return resultList;
    }

    /**
     * 列出已删除项目
     *
     * @param id       ID
     * @param oldItems 旧项目
     * @return {@link List}<{@link EvaluationLog}>
     */
    private List<EvaluationLog> listDeletedItem(Long id, List<EvaluationItem> oldItems) {
        List<EvaluationLog> resultList = new ArrayList<>();
        oldItems.forEach(c -> {
            String older = fun.apply("项目类型", EvaluationItemType.getName(c.getType())) +
                    fun.apply("项目名称", c.getName()) +
                    fun.apply("项目描述", c.getDescription()) +
                    fun.apply("项目分值", c.getScore() + "");
            resultList.add(new EvaluationLog().setEvaluationId(id)
                    .setType(EvaluationLogType.BASE_ITEM.getCode())
                    .setOldData(older)
                    .setNewData(null));
        });
        return resultList;
    }

    /**
     * 列出添加项目
     *
     * @param id       ID
     * @param newItems 旧项目
     * @return {@link List}<{@link EvaluationLog}>
     */
    private List<EvaluationLog> listAddedItem(Long id, List<EvaluationItemUpdateDTO> newItems) {
        List<EvaluationLog> resultList = new ArrayList<>();
        newItems.forEach(c -> {
            String newer = fun.apply("项目类型", EvaluationItemType.getName(c.getType())) +
                    fun.apply("项目名称", c.getName()) +
                    fun.apply("项目描述", c.getDescription()) +
                    fun.apply("项目分值", c.getScore() + "");
            resultList.add(new EvaluationLog().setEvaluationId(id)
                    .setType(EvaluationLogType.BASE_ITEM.getCode())
                    .setOldData(null)
                    .setNewData(newer));
        });
        return resultList;
    }

    public static BiFunction<String, String, String> fun = (fieldName, value) -> fieldName + "：" + value + "；";
    public static BiFunction<String, String, String> funItem = (fieldName, value) -> fieldName + "：" + value + "，";
    public static Function<Boolean, String> isFun = (b) -> b ? "是" : "否";
    public static Function<Boolean, String> enabledFun = (b) -> b ? "启用" : "禁用";
}
